import axios, {
  AxiosError,
  AxiosRequestConfig,
  AxiosResponse,
  AxiosInstance
} from "axios";
import qs from "qs";
// import { ElMessage } from "element-plus";
import router from "/@/router";

import { storageLocal } from "/@/utils/storage";
// import DomMessage from "/@/utils/message/domMessage";
import NotifMessage from "/@/utils/message/notification";

import NProgress from "../progress";

const pendingRequest = new Map(); // 请求对象
// const CancelToken = axios.CancelToken;

let BASE_URL = "";
if (import.meta.env.MODE !== "development") {
  BASE_URL = import.meta.env.VITE_BASE_URL as string;
}

const service: AxiosInstance = axios.create({
  baseURL: BASE_URL, // 使用yapi mock数据
  timeout: 10000, //10秒超时
  headers: {
    Accept: "application/json, text/plain, */*",
    "Content-Type": "application/json",
    loginMethod: "PC"
  }
});

// 请求前的统一处理
service.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    // JWT鉴权处理
    config["loginMethod"] = "PC";
    if (storageLocal.getItem("info")) {
      config.headers.Authorization = storageLocal.getItem("info").accessToken;
    } else {
      storageLocal.removeItem("info");
      // window.location.href = "#login";
    }

    // 获取请求key
    const requestKey = getReqKey(config);
    // 判断是否是重复请求
    if (pendingRequest.has(requestKey)) {
      // 是重复请求
      removeReqKey(requestKey); // 取消
    } else {
      // 设置cancelToken
      // config.cancelToken = new CancelToken(function executor(cancel) {
      //   pendingRequest.set(requestKey, cancel); // 设置
      // });
    }
    NProgress.start();
    return config;
  },
  (error: AxiosError) => {
    return Promise.reject(error);
  }
);

service.interceptors.response.use(
  (response: AxiosResponse) => {
    // 请求对象中删除requestKey
    const requestKey = getReqKey(response?.config);
    requestKey && removeReqKey(requestKey);
    // console.log("[ 🌙 lucux  == response ]", response);

    const res = response.data;
    if (res.code === 200) {
      NProgress.done();

      return res;
    } else {
      showError(res);
      return Promise.reject(res);
    }
  },
  (error: AxiosError) => {
    console.log("[ 🌙 lucux  == error ]", error);
    const requestKey = getReqKey(error?.config);
    requestKey && removeReqKey(requestKey);

    NProgress.done();
    const badMessage: any = error?.response?.data?.message || error.message;
    const code = error?.response?.status;
    showError({ code, message: badMessage });
    return Promise.reject(error);
  }
);

function showError(error: any) {
  if ([401, 403].includes(error.code)) {
    // to re-login
    storageLocal.removeItem("info");
    NotifMessage.error("登录失效，请重新登录");

    router.replace({
      path: "/login"
      // query: { redirect: location.href }
    });
  } else {
    let message = error.message || "服务异常";
    if (message.includes("timeout")) {
      message = "请求超时,请重试";
    }
    // 判断是否是重复请求的错误
    if (!message.includes("epms-admin")) {
      NotifMessage.error(message);
    }
  }
}

// 获取请求key
function getReqKey(config) {
  // 请求方式、请求地址、请求参数生成的字符串来作为是否重复请求的依据
  // const { url, params, data } = config; // 解构出来这些参数
  const methodVal = config?.method ?? "unKnowMethod";
  const paramsVal = config?.params ?? "unKnowParams";
  const dataVal = config?.data ?? "unKnowData";
  const urlVal = config?.url ?? "unKnowUrl";
  // GET ---> params  POST ---> data
  const requestKey = [
    methodVal,
    urlVal,
    qs.stringify(paramsVal),
    qs.stringify(dataVal)
  ].join("&");
  return requestKey;
}

// 取消重复请求
function removeReqKey(key) {
  NProgress.done();
  const cancelToken = pendingRequest?.get(key);
  cancelToken && cancelToken(key); // 取消之前发送的请求
  pendingRequest.delete(key); // 请求对象中删除requestKey
}

const http = {
  get: function (url: string, params?: any) {
    return service.get(url, { params });
  },
  post: function (url: string, params?: any) {
    return service.post(url, params);
  }
};

export default http;
